<template>
  <div class="graph-editor">
    <el-container class="editor-container">
      <el-aside width="280px" class="left-panel">
        <el-container direction="vertical" class="panel-container">

          <el-main class="node-groups-panel">
            <el-collapse v-model="activeNodeGroups" accordion>
              <el-collapse-item v-for="group in visibleNodeGroups" :key="group.id" :name="group.id">
                <template #title>
                  <div class="group-header">
                    <span class="group-title">{{ group.name }}</span>
                    <el-button v-if="!group.isDefault" link type="danger" size="small"
                      @click.stop="removeNodeGroup(group.id)" class="remove-btn">
                      <el-icon>
                        <Remove />
                      </el-icon>
                    </el-button>
                  </div>
                </template>

                <div class="node-types">
                  <div v-for="nodeType in group.types" :key="nodeType.id" class="node-type-item" draggable="true"
                    @dragstart="onDragStart($event, nodeType)" @dragend="onDragEnd">
                    <el-tooltip effect="dark" :content=nodeType.label placement="top-start">
                      <el-image :src="nodeType.image" class="icon-size-image" />
                    </el-tooltip>
                  </div>
                </div>
              </el-collapse-item>
            </el-collapse>

            <!-- 添加更多图形 -->
            <div class="add-more-section">
              <el-button type="primary" link @click="showAddGraphDialog = true" class="add-more-btn">
                <el-icon>
                  <Plus />
                </el-icon>
                添加更多图形
              </el-button>
            </div>
          </el-main>
        </el-container>
      </el-aside>

      <!-- 中间：画布区域 -->
      <el-main class="center-panel">
        <el-container direction="vertical" class="canvas-container">
          <!-- 画布操作栏 -->
          <el-header height="auto" class="canvas-toolbar">
            <el-space>
              <el-text>节点数: {{ nodeCount }}</el-text>
              <el-text>关系数: {{ edgeCount }}</el-text>
              <el-text>当前模式：</el-text>
              <el-tag :type="isLinkingMode ? 'danger' : 'success'">
                {{ isLinkingMode ? '连线模式' : '正常模式' }}
              </el-tag>
              <el-text type="info">缩放: {{ zoomPercentage }}%</el-text>
            </el-space>
          </el-header>

          <!-- 画布 -->
          <el-main class="canvas-main">
            <div id="network-canvas" class="network-canvas" @drop="onDrop" @dragover="onDragOver"></div>
          </el-main>
        </el-container>
      </el-main>

      <!-- 右侧：配置面板 -->
      <el-aside width="320px" class="right-panel">
        <el-container direction="vertical" class="config-container">
          <el-main class="config-main">
            <!-- 视图信息 -->
            <el-card shadow="never" class="config-card">
              <template #header>
                <el-text>视图信息</el-text>
              </template>
              <el-form label-width="80px" size="small">
                <el-form-item label="视图名称">
                  <el-input v-model="name" placeholder="请输入视图名称" />
                </el-form-item>
              </el-form>
            </el-card>

            <!-- 布局配置 -->
            <el-card shadow="never" class="config-card">
              <template #header>
                <el-text>布局配置</el-text>
              </template>
              <el-form :model="options" label-width="80px" size="small">
                <el-form-item label="布局方向">
                  <el-select v-model="options.layout.hierarchical.direction" style="width: 100%">
                    <el-option label="从上到下 (UD)" value="UD" />
                    <el-option label="从下到上 (DU)" value="DU" />
                    <el-option label="从左到右 (LR)" value="LR" />
                    <el-option label="从右到左 (RL)" value="RL" />
                  </el-select>
                </el-form-item>
                <el-form-item label="物理引擎">
                  <el-switch v-model="options.physics.enabled" />
                </el-form-item>
              </el-form>
            </el-card>

            <!-- 连线配置 -->
            <el-card shadow="never" class="config-card">
              <template #header>
                <el-text>连线配置</el-text>
              </template>
              <el-form :model="options" label-width="80px" size="small">
                <el-form-item label="连线平滑度">
                  <el-select v-model="options.edges.smooth.type" style="width: 100%">
                    <el-option label="连续曲线" value="continuous" />
                    <el-option label="离散曲线" value="discrete" />
                    <el-option label="直线" value="straightCross" />
                  </el-select>
                </el-form-item>
                <el-form-item label="连线样式">
                  <el-space>
                    <el-checkbox v-model="options.edges.dashes">虚线</el-checkbox>
                    <el-checkbox v-model="options.edges.arrows.to.enabled">箭头</el-checkbox>
                  </el-space>
                </el-form-item>
                <el-form-item label="节点大小">
                  <el-slider v-model="options.nodes.size" :min="10" :max="50" :show-tooltip="false" />
                  <el-text size="small" type="info" style="margin-left: 8px;">
                    {{ options.nodes.size }}px
                  </el-text>
                </el-form-item>
                <el-form-item label="字体大小">
                  <el-slider v-model="options.nodes.font.size" :min="10" :max="50" :show-tooltip="false" />
                  <el-text size="small" type="info" style="margin-left: 8px;">
                    {{ options.nodes.font.size }}px
                  </el-text>
                </el-form-item>
              </el-form>
            </el-card>
          </el-main>
        </el-container>

        <el-button @click="">取消</el-button>
        <el-button type="primary" @click="handleSave">保存</el-button>
      </el-aside>
    </el-container>

    <!-- 添加图形弹窗 -->
    <el-dialog v-model="showAddGraphDialog" title="添加节点类型">
      <el-tabs tab-position="left" type="border-card">
        <el-tab-pane :label="group.name" v-for="group in extendNodeGroupTypes" class="node-types">
          <div v-for="nodeType in group.types" :key="nodeType.id" class="node-type-item">
            <el-tooltip effect="dark" :content=nodeType.label placement="top-start">
              <el-image :src="nodeType.image" class="icon-size-image" />
            </el-tooltip>
          </div>
        </el-tab-pane>
      </el-tabs>
      <template #footer>
        <el-button @click="showAddGraphDialog = false">取消</el-button>
        <el-button type="primary" @click="addSelectedGraphType" :disabled="!selectedGraphTypeId">
          添加
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { onMounted, onUnmounted, ref, watch, nextTick, computed } from 'vue'
import { DataSet } from 'vis-data'
import { Network } from 'vis-network'
import { Plus, Remove } from '@element-plus/icons-vue'
import { defaultNodeGroupTypes, extendNodeGroupTypes } from '@/views/Analysis/Graph/NodeGroup'
import { mockDataStore } from '@/api/mockGraph';
import { v4 as uuid4 } from 'uuid';


const dataStore = mockDataStore;


const props = defineProps({
  isEditing: Boolean,
  GraphView: Object
})

const emit = defineEmits(['update:modelValue', 'save'])

let network = null
const nodesDataSet = new DataSet(props.GraphView.data.nodes)
const edgesDataSet = new DataSet(props.GraphView.data.edges)
const options = ref(props.GraphView.options)
const name = ref(props.GraphView.name)
let nodeIdCounter = 1

// 响应式状态
const isLinkingMode = ref(false)
const dragData = ref(null)
const selectedNodes = ref([])
const selectedEdges = ref([])
const activeNodeGroups = ref(['network'])

const showAddGraphDialog = ref(false)
const selectedCategory = ref('basic')
const selectedGraphTypeId = ref('')


// 缩放比例
const zoomLevel = ref(1)
const zoomPercentage = computed(() => Math.round(zoomLevel.value * 100))


// 用户添加的节点分组
const userNodeGroups = ref([])
const visibleNodeGroups = computed(() => [...defaultNodeGroupTypes.value, ...userNodeGroups.value])

// 计算属性
const nodeCount = computed(() => nodesDataSet ? nodesDataSet.length : 0)
const edgeCount = computed(() => edgesDataSet ? edgesDataSet.length : 0)


const initNetwork = async () => {
  await nextTick()

  const container = document.getElementById('network-canvas')
  if (!container) return

  const data = {
    nodes: nodesDataSet,
    edges: edgesDataSet
  }

  network = new Network(container, data, options.value)
  network.on('click', handleClick)
  network.on("select", handleSelection)
  network.on("deselectNode", handleDeselection)
  network.on("zoom", handleZoom)
}

const handleClick = (params) => {
  if (params.nodes.length > 0) {
    console.log(params.nodes)
    return
  }
  if (params.edges.length > 0) {
    console.log(params.edges)
  }
}

const handleSelection = (params) => {
  selectedNodes.value = params.nodes
  selectedEdges.value = params.edges
}

const handleDeselection = () => {
  selectedNodes.value = []
  selectedEdges.value = []
}

const handleZoom = (params) => {
  zoomLevel.value = Math.floor(params.scale * 10) / 10
}

const createNodeAtPosition = (position, nodeType) => {
  const newNode = {
    id: uuid4(),
    label: `${nodeType.label}`,
    x: position.x,
    y: position.y,
    shape: nodeType.shape,
    image: nodeType.image
  }

  nodesDataSet.add(newNode)
  return newNode
}

const onDragStart = (event, nodeType) => {
  dragData.value = nodeType
  event.dataTransfer.setData('text/plain', nodeType.id)
  event.dataTransfer.effectAllowed = 'copy'
}

const onDragEnd = () => {
  dragData.value = null
}

const onDragOver = (event) => {
  event.preventDefault()
  event.dataTransfer.dropEffect = 'copy'
}

const onDrop = (event) => {
  event.preventDefault()

  if (!network || !dragData.value) return

  const canvasRect = event.currentTarget.getBoundingClientRect()
  const x = event.clientX - canvasRect.left
  const y = event.clientY - canvasRect.top
  const canvasPoint = network.DOMtoCanvas({ x, y })
  createNodeAtPosition(canvasPoint, dragData.value)
  dragData.value = null
}

const enableLinkingMode = () => {
  if (network && !isLinkingMode.value) {
    isLinkingMode.value = true
    network.addEdgeMode()
  }
}

const disableLinkingMode = () => {
  if (network && isLinkingMode.value) {
    isLinkingMode.value = false
    network.disableEditMode()
  }
}


const addSelectedGraphType = () => {
  if (!selectedGraphTypeId.value) return

  // 在所有分类中查找选中的图形类型
  for (const category of Object.values(extendNodeGroupTypes.value)) {
    const graphType = category.find(g => g.id === selectedGraphTypeId.value)
    if (graphType) {
      // 检查是否已经添加
      const exists = userNodeGroups.value.find(g => g.id === graphType.id)
      if (!exists) {
        userNodeGroups.value.push({
          id: graphType.id,
          name: graphType.name,
          isDefault: false,
          types: graphType.types
        })
        // 自动展开新添加的分组
        activeNodeGroups.value.push(graphType.id)
      }
      break
    }
  }
  showAddGraphDialog.value = false
  selectedGraphTypeId.value = ''
}

const removeNodeGroup = (groupId) => {
  userNodeGroups.value = userNodeGroups.value.filter(g => g.id !== groupId)
  activeNodeGroups.value = activeNodeGroups.value.filter(id => id !== groupId)
}

const handleKeyDown = (event) => {
  if (event.ctrlKey && !isLinkingMode.value) {
    enableLinkingMode()
    event.preventDefault()
  }

  if (event.key === 'Delete' && (selectedNodes.value.length > 0 || selectedEdges.value.length > 0)) {
    event.preventDefault()
    if (selectedNodes.value.length > 0) {
      nodesDataSet.remove(selectedNodes.value)
    }
    if (selectedEdges.value.length > 0) {
      edgesDataSet.remove(selectedEdges.value)
    }
  }
}

const handleKeyUp = (event) => {
  if (!event.ctrlKey && isLinkingMode.value) {
    disableLinkingMode()
  }
}

// 监听配置变化
watch(options, () => {
  if (network) {
    network.setOptions(options.value)
  }
}, { deep: true })


const handleSave = () => {
  const GraphView = {
    name: name.value,
    data: {
      nodes: nodesDataSet.get(),
      edges: edgesDataSet.get()
    },
    options: options.value
  }
  if (props.GraphView?.id) {
    dataStore.updateView(props.GraphView?.id, { ...GraphView, id: props.GraphView?.id, })
  }
  else {
    dataStore.createView(GraphView)
  }
  emit('save')
}

// 生命周期
onMounted(() => {
  initNetwork()
  document.addEventListener('keydown', handleKeyDown)
  document.addEventListener('keyup', handleKeyUp)

})

onUnmounted(() => {
  if (network) {
    network.destroy()
  }
  document.removeEventListener('keydown', handleKeyDown)
  document.removeEventListener('keyup', handleKeyUp)
})
</script>

<style scoped>
.graph-editor {
  height: 90%;
  display: flex;
  flex-direction: column;
  background: #f5f7fa;
}

.editor-header {
  display: flex;
  align-items: center;
  padding: 0 20px;
  background: white;
  border-bottom: 1px solid #e4e7ed;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.editor-container {
  flex: 1;
  overflow: hidden;
}

/* 左侧面板 */
.left-panel {
  background: white;
  border-right: 1px solid #e4e7ed;
}

.panel-container {
  height: 100%;
}

.node-groups-panel {
  padding: 16px;
  overflow: hidden;
}

:deep(.el-collapse) {
  border: none;
}

:deep(.el-collapse-item__header) {
  border: none;
  font-weight: 600;
  background: #f8f9fa;
}

:deep(.el-collapse-item__content) {
  padding: 0;
}

.group-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.group-title {
  flex: 1;
}

.remove-btn {
  padding: 4px;
}

/* .node-types {
  padding: 8px 0;
} */

.node-type-item {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  margin: 4px 0;
  border-radius: 4px;
  cursor: grab;
  transition: all 0.2s;
  user-select: none;
}

.node-type-item:hover {
  background: #f5f7fa;
}

.node-type-item:active {
  cursor: grabbing;
}

.node-icon {
  width: 24px;
  height: 24px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 8px;
  border: 2px solid;
  font-size: 12px;
}

.node-label {
  color: #606266;
  font-size: 12px;
  font-weight: 500;
}

.add-more-section {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid #e4e7ed;
}

.add-more-btn {
  width: 100%;
  justify-content: center;
}

.help-panel {
  padding: 16px;
  height: auto;
}

.help-card {
  border: 1px solid #e4e7ed;
}

.help-card :deep(.el-card__header) {
  padding: 12px 16px;
  border-bottom: 1px solid #e4e7ed;
}

.help-items {
  width: 100%;
}

/* 中间面板 */
.center-panel {
  padding: 0;
  background: white;
}

.canvas-container {
  height: 90%;
}

.canvas-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid #e4e7ed;
  background: white;
}

.canvas-main {
  padding: 0;
}

.network-canvas {
  width: 100%;
  height: 90%;
  border: none;
}

/* 右侧面板 */
.right-panel {
  background: white;
  border-left: 1px solid #e4e7ed;
}

.config-container {
  height: 90%;
}

.config-main {
  padding: 16px;
  overflow-y: auto;
  max-height: calc(100vh - 120px);
}

.config-card {
  margin-bottom: 16px;
  border: 1px solid #e4e7ed;
}

.config-card:last-child {
  margin-bottom: 0;
}

.config-card :deep(.el-card__header) {
  padding: 12px 16px;
  border-bottom: 1px solid #e4e7ed;
}

.config-card :deep(.el-form-item) {
  margin-bottom: 16px;
}

.config-card :deep(.el-form-item:last-child) {
  margin-bottom: 0;
}

.action-footer {
  padding: 16px;
  height: auto;
  border-top: 1px solid #e4e7ed;
  background: white;
}

.graph-categories {
  border-right: 1px solid #e4e7ed;
}

.graph-preview {
  padding: 0 16px;
}

.graph-types {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.graph-type-item {
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.graph-type-item:hover {
  border-color: #409eff;
}

.graph-type-item.selected {
  border-color: #409eff;
  background: #f0f9ff;
}

.graph-type-header {
  margin-bottom: 8px;
}

.graph-type-preview {
  display: flex;
  gap: 8px;
}

.preview-node {
  width: 32px;
  height: 32px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid;
  font-size: 14px;
}

.icon-size-image {
  width: 25px;
  height: 25px;
}

.node-types {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}

.icon-item {
  flex: 0 0 20%;
  /* 每个图标项占容器宽度的20% */
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 5px;
  /* 可选：内边距 */
  box-sizing: border-box;
}
</style>